﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows.Controls.Ribbon;
using SHomeWorkshop.LunarConcept.Controls;
using System.Xml;
using SHomeWorkshop.LunarConcept.Tools;
using SHomeWorkshop.LunarConcept.ModifingManager;
using System.Windows;
using SHomeWorkshop.LunarConcept.Widgets;
using System.Windows.Media;

namespace SHomeWorkshop.LunarConcept.Commands
{
    /// <summary>
    /// 创建时间：2012年2月3日
    /// 创建者：  杨震宇
    /// 
    /// 主要用途：根据当前部件决定是否跟随插入一个类似部件。例如：当前部件是文本块，则添加一个文本块并立即进行编辑。
    ///           若没有当前部件，则向当前插入点位置插入一个新的TextArea部件并立即进入编辑状态。
    ///           或当前部件是图片框，则插入一个图片框，并立即进入文本编辑状态（新图片框不使用前一个图片框的图像数据）。
    ///           若当前部件是矩形，则插入一个新矩形，并立即进入文本编辑状态。
    /// 
    ///           ——在内部是调用“InsertSimilarWidgetAndEditCommand”的Execute()方法来实现前半部分功能，
    ///           调用“EditCommand”的Execute()方法来实现后半部分功能。
    /// </summary>
    public static class InsertSimilarWidgetAndEditCommand
    {
        #region 构造方法=====================================================================================================

        /// <summary>
        /// [静态][构造方法]
        /// 
        /// ——此方法会初始化并向WPF系统注册一个RoutedUICommand。
        /// </summary>
        static InsertSimilarWidgetAndEditCommand()//类型构造器
        {
            routedUICmd = new RoutedUICommand(
                "InsertSimilarWidgetAndEditCommand",
                "InsertSimilarWidgetAndEditCommand",
                typeof(InsertSimilarWidgetAndEditCommand),//创建RoutedUICommand对象
                null);

            cmdBinding.Command = routedUICmd;
            cmdBinding.CanExecute += new CanExecuteRoutedEventHandler(cmdBinding_CanExecute);
            cmdBinding.Executed += new ExecutedRoutedEventHandler(cmdBinding_Executed);
        }

        #endregion

        #region 字段与属性===================================================================================================

        private static CommandBinding cmdBinding = new CommandBinding();
        /// <summary>
        /// 用在主窗口CommandBindings集合中的命令绑定。
        /// 
        /// 它的Command是RoutedUICommand。
        /// ——因此，RoutedUICommand是否可以运行将由CmdBinding的CanExecute事件决定。
        /// ——而且，RoutedUICommand的执行也是通过CmdBinding的Execute事件来进行的。
        /// </summary>
        public static CommandBinding CmdBinding
        {
            get { return cmdBinding; }
        }

        private static RoutedUICommand routedUICmd;
        /// <summary>
        /// [只读静态属性]表示在WPF系统中注册的一个RoutedUICommand。
        /// ——必须和CommandBinding配合才能使用。
        ///     CommandBinding要添加到主窗口的CommandBindings集合中；
        ///     RoutedUICommand则要向WPF系统注册。
        ///     
        /// ★说明：使用静态属性是因为这样在Xaml代码中比较便于绑定。
        /// </summary>
        public static RoutedUICommand RoutedUICmd
        {
            get { return routedUICmd; }
        }

        #endregion

        #region 方法=========================================================================================================

        /// <summary>
        /// 判断命令是否可以执行。
        /// ——由于可以直接调用Execute()方法，因此，即使被禁用，也不是不能执行相关功能！！！
        /// </summary>
        static void cmdBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            //考虑到性能问题，全部取消此判断。反正执行时会判断。
            //if (Globals.MainWindow == null)
            //{
            //    e.CanExecute = false; return;
            //}

            //EditorManager manager = Globals.MainWindow.EditorManager;
            //if (manager == null)
            //{
            //    e.CanExecute = false; return;
            //}

            //PageEditor pe = manager.GetMainSelectedPageEditor();

            //e.CanExecute = (pe != null && pe.XmlData != null);

            e.CanExecute = true;
            return;
        }

        /// <summary>
        /// 命令被触发时，会调用本事件处理器方法。
        /// ——本方法实际上是调用ExeCute()这个静态方法来实现特定功能。
        /// </summary>
        static void cmdBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            LunarMessage.Warning(Execute(0));//注意，这里要给参数。
        }

        /// <summary>
        /// [公开静态方法]即使此命令处于禁用状态，也可以通过代码调用此方法来执行特定任务！！！
        /// 
        /// 当被绑定的命令被调用（触发）时，会引发cmdBinding_Executed事件。
        /// 在cmdBinding_Executed事件处理器方法中已添加了调用Execute()方法的代码。
        /// 
        /// ——因此，触发命令，就相当于调用此方法！！！
        /// 
        /// 添加文本框或矩形框，但起点水平坐标会有个偏移量。
        /// </summary>
        /// <param name="offsetX">水平坐标偏移量。默认应传入。</param>
        /// <param name="withPolyLineLinked">表示是否自带折线。仅对TextArea有效。</param>
        /// <param name="atRight">是否在水平偏移量上加上当前部件的宽度。</param>
        /// <param name="atTop">目前只有TextArea才支持，将新TextArea添加到右上角时使用。</param>
        public static string Execute(double offsetX, bool withPolyLineLinked = false, bool atRight = false, bool atTop = false)
        {
            if (Globals.MainWindow == null) return "　　未找到Globals.MainWindow。";

            EditorManager manager = Globals.MainWindow.EditorManager;
            if (manager == null) return "　　未找到页面管理器。";

            PageEditor pe = manager.GetMainSelectedPageEditor();
            if (pe == null) return "　　未找到活动页面。";

            Widgets.Widget mainWidget = pe.GetMainSelectedWidget();
            if (mainWidget == null)
            {
                if (Commands.InsertTextAreaCommand.Execute() == string.Empty)
                {
                    return Commands.EditCommand.Execute();
                }
                else
                {
                    return "　　未能添加文本块。";
                }
            }
            else
            {
                //在此部件下部添加一个新文本区，并直接进入编辑状态。
                //新文本区的基本格式与上一个相同。

                string insertResult = string.Empty;

                switch (mainWidget.WidgetClassName)
                {
                    case "TextArea":
                        {
                            Widgets.TextArea curTextArea = mainWidget as Widgets.TextArea;
                            insertResult = TryToAddNewTextArea(curTextArea, offsetX, 10, withPolyLineLinked, atRight, atTop);
                            break;
                        }
                    case "PictureBox":
                        {
                            Widgets.PictureBox curPictureBox = mainWidget as Widgets.PictureBox;
                            insertResult = TryToAddNewPictureBox(curPictureBox, offsetX, 10);
                            break;
                        }
                    case "EllipseWidget":
                        {
                            Widgets.EllipseWidget curEllipse = mainWidget as Widgets.EllipseWidget;
                            insertResult = TryToAddNewEllipse(curEllipse, offsetX, 10);
                            break;
                        }
                    case "RectangleWidget":
                        {
                            Widgets.RectangleWidget curRectangle = mainWidget as Widgets.RectangleWidget;
                            insertResult = TryToAddNewRectangle(curRectangle, offsetX, 10);
                            break;
                        }
                    case "RhombWidget":
                        {
                            Widgets.RhombWidget curRhomb = mainWidget as Widgets.RhombWidget;
                            insertResult = TryToAddNewRhomb(curRhomb, offsetX, 10);
                            break;
                        }
                    case "TriangleWidget":
                        {
                            Widgets.TriangleWidget curTriangle = mainWidget as Widgets.TriangleWidget;
                            insertResult = TryToAddTriangle(curTriangle, offsetX, 10);
                            break;
                        }
                    default:
                        {
                            return string.Format("　　不支持在 {0} 类型的部件上执行此操作。", mainWidget.WidgetClassLocalName);
                        }
                }

                if (insertResult == string.Empty)
                {
                    return Commands.EditCommand.Execute();
                }
                else return insertResult;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="curTextArea"></param>
        /// <param name="offsetX"></param>
        /// <param name="offsetY"></param>
        /// <param name="withPolyLineLinked">只有Ctrl+Enter才会用true参数来调用，这样添加的总是备注文本块，WidgetTitleLevel总是正文。</param>
        /// <param name="atRight">是否加上当前部件的宽度。此参数目前只有当withPolyLineLinkde参数为true时才起作用。默认值为false。</param>
        /// <param name="atTop">目前只有TextArea才支持，将新TextArea添加到右上角时使用。</param>
        /// <returns></returns>
        private static string TryToAddNewTextArea(TextArea curTextArea, double offsetX, double offsetY, bool withPolyLineLinked = false, bool atRight = false, bool atTop = false)
        {
            if (curTextArea == null) return "　　未传入文本块。";
            if (curTextArea.MasterEditor == null) return "　　未找到传入的文本块所在页面。";
            if (curTextArea.MasterEditor.MasterManager == null) return "　　未找到页面管理器。";

            PageEditor pe = curTextArea.MasterEditor;
            EditorManager manager = curTextArea.MasterEditor.MasterManager;

            Enums.TitleStyle newTitleLevel;

            Point topLeft = curTextArea.TopLeft;
            //留下一段空白，以便新文本块大部分超过右边界时可以拖出来。
            if (offsetX < 0)
            {
                if (curTextArea.TitleLevel > Enums.TitleStyle.MainTitle)
                {
                    newTitleLevel = curTextArea.TitleLevel - 1;
                }
                else
                {
                    offsetX = 0;//到最左边了
                    newTitleLevel = curTextArea.TitleLevel;
                }

                if (topLeft.X - Math.Abs(offsetX) > 0)
                {
                    topLeft.X += offsetX;//向左
                }
            }
            else if (offsetX > 0)
            {
                if (curTextArea.TitleLevel < Enums.TitleStyle.Normal)
                {
                    newTitleLevel = curTextArea.TitleLevel + 1;
                }
                else
                {
                    offsetX = 0;//已到最右边。
                    newTitleLevel = curTextArea.TitleLevel;
                }

                //留下一段空白，以便新文本块大部分超过右边界时可以拖出来。
                if ((topLeft.X + offsetX) < pe.ActualWidth - 10)
                {
                    topLeft.X += offsetX;
                }
            }
            else newTitleLevel = curTextArea.TitleLevel;

            //使用Ctrl+Enter，withPolyLineLinked为true
            //此时，新添加的总是备注（总是正文级别）
            if (withPolyLineLinked || atRight) newTitleLevel = Enums.TitleStyle.Normal;

            Point bottomRight = curTextArea.BottomRight;

            bool addInNewPage = false;
            if (bottomRight.Y + 10 + (bottomRight.Y - topLeft.Y) > pe.EditArea.Bottom)
            {
                int indexOfcurPe = manager.Children.IndexOf(pe);
                if (indexOfcurPe >= (manager.Children.Count - 1))
                {
                    //已是最后一个。
                    Commands.InsertNewPageEditorCommand.Execute();
                    pe = manager.GetMainSelectedPageEditor();
                }
                else
                {
                    pe = manager.Children[indexOfcurPe + 1] as PageEditor;
                }

                if (pe == null) return "　　未找到目标页面。";

                addInNewPage = true;
            }

            if (atRight)
            {
                pe.BaseInsertPoint = new Point(topLeft.X + curTextArea.ActualWidth + Globals.MainWindow.EditorManager.DefaultFontSize * 2 + 10, bottomRight.Y + 10);
            }
            else
            {
                pe.BaseInsertPoint = new Point(topLeft.X, bottomRight.Y + 10);
            }

            if (atTop)
            {
                Point p = pe.BaseInsertPoint;
                pe.BaseInsertPoint = new Point(p.X, curTextArea.TopLeft.Y - Globals.MainWindow.EditorManager.DefaultFontSize - 30);
            }

            XmlNode peWidgetSetNode = pe.WidgetSetNode;
            if (peWidgetSetNode == null)
            {
                return "　　未找到目标页面的后台WidgetSet节点。";
            }

            XmlNode newTextAreaNode = peWidgetSetNode.AppendXmlAsChild(Properties.Resources.TextAreaXml);

            TextArea ta = new TextArea(pe);
            ta.XmlData = newTextAreaNode;
            ta.NewID();

            if (addInNewPage)
            {
                pe.BaseInsertPoint = new Point(curTextArea.TopLeft.X, pe.EditArea.Top + offsetY);
                ta.Location = pe.BaseInsertPoint;
            }
            else
            {
                ta.Location = pe.BaseInsertPoint;
            }

            //设置相似属性。
            if (curTextArea.IsWidgetPropertySetted(XmlTags.WidgetOpacityTag)) ta.WidgetOpacity = curTextArea.WidgetOpacity;
            if (curTextArea.IsWidgetPropertySetted(XmlTags.IsShadowVisibleTag)) ta.IsShadowVisible = curTextArea.IsShadowVisible;//其实这个不加更好，运行速度成问题。
            if (curTextArea.IsWidgetPropertySetted(XmlTags.WidgetForeColor)) ta.WidgetForeColor = curTextArea.WidgetForeColor;
            if (curTextArea.IsWidgetPropertySetted(XmlTags.WidgetLineWidthTag)) ta.WidgetLineWidth = curTextArea.WidgetLineWidth;
            if (curTextArea.IsWidgetPropertySetted(XmlTags.WidgetLineColorTag)) ta.WidgetLineColor = curTextArea.WidgetLineColor;
            if (curTextArea.IsWidgetPropertySetted(XmlTags.WidgetPaddingTag)) ta.WidgetPadding = curTextArea.WidgetPadding;

            //Backcolor是特殊的，需要另作处理，因为支持了自定义图像背景
            var srcWidgetBackColorName = BrushManager.GetName(curTextArea.WidgetBackColor);
            if (string.IsNullOrWhiteSpace(srcWidgetBackColorName) || srcWidgetBackColorName == typeof(ImageBrush).Name)
            {
                if (string.IsNullOrWhiteSpace(curTextArea.ImageBase64) == false)
                {
                    ta.ImageBase64 = curTextArea.ImageBase64;
                }
            }
            else
            {
                if (curTextArea.IsWidgetPropertySetted(XmlTags.WidgetBackColor))
                {
                    ta.WidgetBackColor = curTextArea.WidgetBackColor;
                }
            }

            ta.TitleLevel = newTitleLevel;

            ModifingInfo info = new ModifingInfo();
            info.ModifingDescription = "添加文本框";
            manager.GetSelectedPageEditorStatus(info);
            manager.GetSelectedWidgetStatus_Old(info);

            ModifingItem<Action, ModifingInfo> mi = new ModifingItem<Action, ModifingInfo>(info);

            Action actAddTextArea = new Action(ActionType.WidgetAdded, pe.Id, ta.Id, null, ta.XmlData.OuterXml);

            pe.AddWidget(ta);
            ta.RefreshLocation();

            ta.SelectOnlySelf();

            mi.AddAction(actAddTextArea);

            info.NewMainSelectedWidgetID = ta.Id;

            #region 添加相似关系线


            if (addInNewPage == false)
            {
                if (withPolyLineLinked)
                {
                    //添加一条折线作连接线这个用于Ctrl+Enter调用
                    XmlNode widgetSetNode = pe.WidgetSetNode;
                    if (widgetSetNode != null)
                    {
                        XmlNode newLinkLineNode = widgetSetNode.AppendXmlAsChild(Properties.Resources.PolyLineXml);
                        Widgets.PolyLineWidget newline = new PolyLineWidget(pe);
                        newline.XmlData = newLinkLineNode;

                        newline.StartMasterId = curTextArea.Id;
                        newline.EndMasterId = ta.Id;

                        newline.Direction = System.Windows.Controls.Orientation.Vertical;

                        if (atRight)
                        {
                            newline.LineForm = Enums.PolyLineForms.PolyLine;
                        }
                        else
                        {
                            newline.LineForm = Enums.PolyLineForms.CLine;
                        }

                        newline.LineDash = LineDashType.DashType.Dash;
                        newline.Arrows = Enums.ArrowType.None;
                        newline.WidgetLineWidth = 1;

                        newline.NewID();
                        Action actAddLinkdeLine = new Action(ActionType.WidgetAdded, pe.Id, newline.Id, null, newline.XmlData.OuterXml);

                        pe.AddWidget(newline);
                        newline.RefreshLocation();

                        mi.AddAction(actAddLinkdeLine);

                        List<Widgets.Interfaces.ILinkableLine> newLinkedLines = new List<Widgets.Interfaces.ILinkableLine>();
                        newLinkedLines.Add(newline);
                        pe.RefreshLinkedLines(mi, newLinkedLines);
                    }
                }
                else
                {
                    AddSimilarLinkedLine(curTextArea, pe, ta, mi);
                }
            }

            #endregion

            manager.RegisterModifingItem(mi);
            manager.RefreshAutoNumberStrings();

            return string.Empty;
        }

        internal static void AddSimilarLinkedLine(Widgets.Interfaces.ICanBeLinkedWidget curCanBeLinkedWidget,
            PageEditor pe, Widgets.Interfaces.ICanBeLinkedWidget newCanBeLinkedWidget,
            ModifingItem<Action, ModifingInfo> mi)
        {
            XmlNode widgetSetNode = pe.WidgetSetNode;
            if (widgetSetNode != null)
            {
                List<Widgets.Interfaces.ILinkableLine> linkedLinesList = curCanBeLinkedWidget.GetLinkedLines();
                if (linkedLinesList.Count > 0)
                {
                    for (int i = linkedLinesList.Count - 1; i >= 0; i--)
                    {
                        if (linkedLinesList[i].EndMasterId != curCanBeLinkedWidget.Id)
                        {
                            linkedLinesList.RemoveAt(i);
                        }
                    }

                    if (linkedLinesList.Count == 1)//有且仅有一条连接线指向源部件。
                    {
                        AddSimilarLinkedLine(curCanBeLinkedWidget, pe, newCanBeLinkedWidget, mi, widgetSetNode, linkedLinesList[0]);
                    }
                }
            }
        }

        internal static void AddSimilarLinkedLine(Widgets.Interfaces.ICanBeLinkedWidget curCanBeLinkedWidget,
            PageEditor pe, Widgets.Interfaces.ICanBeLinkedWidget newCanBeLinkedWidget,
            ModifingItem<Action, ModifingInfo> mi, XmlNode widgetSetNode,
            Widgets.Interfaces.ILinkableLine linkedLine)
        {
            Widgets.StraitLineWidget sw = linkedLine as Widgets.StraitLineWidget;
            if (sw != null)
            {
                //添加相似直线连接线
                XmlNode newLinkLineNode = widgetSetNode.AppendXmlAsChild(Properties.Resources.StraitLineXml);
                Widgets.StraitLineWidget newline = new StraitLineWidget(pe);
                newline.XmlData = newLinkLineNode;

                newline.Arrows = linkedLine.Arrows;

                newline.StartLinkTo = sw.StartLinkTo;
                newline.EndLinkTo = sw.EndLinkTo;


                if (linkedLine.EndMasterId == curCanBeLinkedWidget.Id)
                {
                    newline.StartMasterId = linkedLine.StartMasterId;
                    newline.EndMasterId = newCanBeLinkedWidget.Id;
                }
                else
                {
                    newline.StartMasterId = newCanBeLinkedWidget.Id;
                    newline.EndMasterId = linkedLine.EndMasterId;
                }

                newline.NewID();
                Action actAddLinkdeLine = new Action(ActionType.WidgetAdded, pe.Id, newline.Id, null, newline.XmlData.OuterXml);

                pe.AddWidget(newline);
                newline.RefreshLocation();

                mi.AddAction(actAddLinkdeLine);

                List<Widgets.Interfaces.ILinkableLine> newLinkedLines = new List<Widgets.Interfaces.ILinkableLine>();
                newLinkedLines.Add(newline);
                pe.RefreshLinkedLines(mi, newLinkedLines);
            }
            else
            {
                //添加相似的曲线连接线
                Widgets.BezierLineWidget bw = linkedLine as Widgets.BezierLineWidget;
                if (bw != null)
                {
                    XmlNode newLinkLineNode = widgetSetNode.AppendXmlAsChild(Properties.Resources.BezierLineXml);
                    Widgets.BezierLineWidget newline = new BezierLineWidget(pe);
                    newline.XmlData = newLinkLineNode;

                    newline.Arrows = linkedLine.Arrows;

                    newline.NewID();
                    newline.LineForm = bw.LineForm;
                    Widget startWidget;
                    Widget endWidget;

                    if (linkedLine.EndMasterId == curCanBeLinkedWidget.Id)
                    {
                        newline.StartMasterId = linkedLine.StartMasterId;
                        newline.EndMasterId = newCanBeLinkedWidget.Id;

                        startWidget = pe.GetWidget(linkedLine.StartMasterId);
                        endWidget = curCanBeLinkedWidget as Widget;
                    }
                    else
                    {
                        newline.StartMasterId = newCanBeLinkedWidget.Id;
                        newline.EndMasterId = linkedLine.EndMasterId;

                        startWidget = curCanBeLinkedWidget as Widget;
                        endWidget = pe.GetWidget(linkedLine.StartMasterId);
                    }

                    if (startWidget != null && endWidget != null)
                    {
                        Rect startRect = startWidget.OuterRect;
                        Rect endRect = endWidget.OuterRect;

                        Point startCenter = new Point(startRect.Left + startRect.Width / 2, startRect.Top + startRect.Height / 2);
                        Point endCenter = new Point(endRect.Left + endRect.Width / 2, endRect.Top + endRect.Height / 2);

                        Tools.PointToRect.ArrowPoints startApt = Tools.PointToRect.GetCrossPointToRect(startRect, endCenter);
                        Tools.PointToRect.ArrowPoints endApt = Tools.PointToRect.GetCrossPointToRect(endRect, startCenter);

                        Point startCPPoint = new Point(startApt.Top.X + (endApt.Top.X - startApt.Top.X) / 3,
                            startApt.Top.Y + (endApt.Top.Y - startApt.Top.Y) / 3);
                        Point endCPPoint = new Point(endApt.Top.X - (endApt.Top.X - startApt.Top.X) / 3,
                            endApt.Top.Y - (endApt.Top.Y - startApt.Top.Y) / 3);

                        newline.StartCPPoint = startCPPoint;
                        newline.EndCPPoint = endCPPoint;
                    }

                    if (bw.LineForm == Enums.BezierLineForms.MindMapLinkLine)
                    {
                        newline.WidgetLineColor = bw.WidgetLineColor;
                        newline.WidgetForeColor = bw.WidgetForeColor;
                        newline.WidgetBackColor = bw.WidgetBackColor;
                    }

                    Action actAddLinkdeLine = new Action(ActionType.WidgetAdded, pe.Id, newline.Id, null, newline.XmlData.OuterXml);

                    pe.AddWidget(newline);
                    newline.RefreshLocation();

                    mi.AddAction(actAddLinkdeLine);

                    List<Widgets.Interfaces.ILinkableLine> newLinkedLines = new List<Widgets.Interfaces.ILinkableLine>();
                    newLinkedLines.Add(newline);
                    pe.RefreshLinkedLines(mi, newLinkedLines);
                }
                else
                {
                    //添加相似的折线连接线。
                    Widgets.PolyLineWidget pw = linkedLine as Widgets.PolyLineWidget;
                    if (pw != null)
                    {
                        XmlNode newLinkLineNode = widgetSetNode.AppendXmlAsChild(Properties.Resources.PolyLineXml);
                        Widgets.PolyLineWidget newline = new PolyLineWidget(pe);
                        newline.XmlData = newLinkLineNode;

                        if (linkedLine.EndMasterId == curCanBeLinkedWidget.Id)
                        {
                            newline.StartMasterId = linkedLine.StartMasterId;
                            newline.EndMasterId = newCanBeLinkedWidget.Id;
                        }
                        else
                        {
                            newline.StartMasterId = newCanBeLinkedWidget.Id;
                            newline.EndMasterId = linkedLine.EndMasterId;
                        }

                        newline.NewID();

                        switch (pw.LineForm)
                        {
                            case Enums.PolyLineForms.BigFishBone:
                                {
                                    //添加相似鱼骨线之前，先移动新添加的ICanLinkedWidget应移动到的大致位置。

                                    int newCanLinkedWidgetAtArea = 0;//新节点相对于鱼头节点所在的坐标象限

                                    double preWidgetLineWidth = 1.0;

                                    newCanLinkedWidgetAtArea = GetArea(curCanBeLinkedWidget, pe, newCanBeLinkedWidget, ref preWidgetLineWidth);

                                    switch (newCanLinkedWidgetAtArea)
                                    {
                                        case 1://在第一象限
                                        case 4://在第四象限
                                            {
                                                Rect curRect = curCanBeLinkedWidget.OuterRect;
                                                Point curCenter = new Point(curRect.X + curRect.Width / 2, curRect.Y + curRect.Height / 2);

                                                newCanBeLinkedWidget.MoveLeftSiderTo(mi, curCenter.X + 10);
                                                break;
                                            }
                                        case 2://在第二象限
                                        case 3://在第三象限
                                            {
                                                Rect curRect = curCanBeLinkedWidget.OuterRect;
                                                Point curCenter = new Point(curRect.X + curRect.Width / 2, curRect.Y + curRect.Height / 2);
                                                newCanBeLinkedWidget.MoveRightSiderTo(mi, curCenter.X - 10);
                                                break;
                                            }
                                    }

                                    newline.LineForm = Enums.PolyLineForms.MediumFishBone;
                                    newline.WidgetLineWidth = Math.Max(preWidgetLineWidth - 1, 1);
                                    newline.Arrows = Enums.ArrowType.None;
                                    break;
                                }
                            case Enums.PolyLineForms.MediumFishBone://相似鱼骨线。
                                {
                                    //添加相似鱼骨线之前，先移动新添加的ICanLinkedWidget应移动到的大致位置。

                                    int newCanLinkedWidgetAtArea = 0;//新节点相对于鱼头节点所在的坐标象限

                                    double preWidgetLineWidth = 1.0;

                                    newCanLinkedWidgetAtArea = GetArea(curCanBeLinkedWidget, pe, newCanBeLinkedWidget, ref preWidgetLineWidth);

                                    switch (newCanLinkedWidgetAtArea)
                                    {
                                        case 1://在第一象限
                                            {
                                                Rect curRect = curCanBeLinkedWidget.OuterRect;

                                                if (newCanBeLinkedWidget.TopLeft.Y > curCanBeLinkedWidget.TopLeft.Y)
                                                {
                                                    //向下，横坐标左移
                                                    newCanBeLinkedWidget.MoveLeftSiderTo(mi, curRect.X - (curRect.Height + 10) / Math.Sqrt(3));
                                                }
                                                else if (newCanBeLinkedWidget.TopLeft.Y < curCanBeLinkedWidget.TopLeft.Y)
                                                {
                                                    //向上，横坐标右移
                                                    newCanBeLinkedWidget.MoveLeftSiderTo(mi, curRect.X + (curRect.Height + 10) / Math.Sqrt(3));

                                                }//else 水平，不改横坐标。
                                                break;
                                            }
                                        case 4://在第四象限
                                            {
                                                Rect curRect = curCanBeLinkedWidget.OuterRect;

                                                if (newCanBeLinkedWidget.TopLeft.Y > curCanBeLinkedWidget.TopLeft.Y)
                                                {
                                                    //向下，横坐标右移
                                                    newCanBeLinkedWidget.MoveLeftSiderTo(mi, curRect.X + (curRect.Height + 10) / Math.Sqrt(3));
                                                }
                                                else if (newCanBeLinkedWidget.TopLeft.Y < curCanBeLinkedWidget.TopLeft.Y)
                                                {
                                                    //向上，横坐标左移
                                                    newCanBeLinkedWidget.MoveLeftSiderTo(mi, curRect.X - (curRect.Height + 10) / Math.Sqrt(3));

                                                }//else 水平，不改横坐标
                                                break;
                                            }
                                        case 2://在第二象限
                                            {
                                                Rect curRect = curCanBeLinkedWidget.OuterRect;

                                                if (newCanBeLinkedWidget.TopLeft.Y > curCanBeLinkedWidget.TopLeft.Y)
                                                {
                                                    //向下，横坐标右移
                                                    newCanBeLinkedWidget.MoveRightSiderTo(mi, curRect.Right + (curRect.Height + 10) / Math.Sqrt(3));
                                                }
                                                else if (newCanBeLinkedWidget.TopLeft.Y < curCanBeLinkedWidget.TopLeft.Y)
                                                {
                                                    //向上，横坐标左移，
                                                    newCanBeLinkedWidget.MoveRightSiderTo(mi, curRect.Right - (curRect.Height + 10) / Math.Sqrt(3));

                                                }//else 水平，不改横坐标
                                                break;
                                            }
                                        case 3://在第三象限
                                            {
                                                Rect curRect = curCanBeLinkedWidget.OuterRect;
                                                if (newCanBeLinkedWidget.TopLeft.Y > curCanBeLinkedWidget.TopLeft.Y)
                                                {
                                                    //向下，横坐标左移
                                                    newCanBeLinkedWidget.MoveRightSiderTo(mi, curRect.Right - (curRect.Height + 10) / Math.Sqrt(3));
                                                }
                                                else if (newCanBeLinkedWidget.TopLeft.Y < curCanBeLinkedWidget.TopLeft.Y)
                                                {
                                                    //向上，械坐标右移
                                                    newCanBeLinkedWidget.MoveRightSiderTo(mi, curRect.Right + (curRect.Height + 10) / Math.Sqrt(3));

                                                }//else 水平，不改横坐标
                                                break;
                                            }
                                    }

                                    newline.LineForm = Enums.PolyLineForms.MediumFishBone;
                                    newline.WidgetLineWidth = preWidgetLineWidth;
                                    newline.Arrows = Enums.ArrowType.None;
                                    break;
                                }
                            default:
                                {
                                    newline.LineForm = pw.LineForm;
                                    newline.LineDash = pw.LineDash;
                                    newline.WidgetLineWidth = pw.WidgetLineWidth;
                                    newline.Arrows = linkedLine.Arrows;
                                    break;
                                }
                        }

                        Action actAddLinkdeLine = new Action(ActionType.WidgetAdded, pe.Id, newline.Id, null, newline.XmlData.OuterXml);

                        pe.AddWidget(newline);
                        newline.RefreshLocation();

                        mi.AddAction(actAddLinkdeLine);

                        List<Widgets.Interfaces.ILinkableLine> newLinkedLines = new List<Widgets.Interfaces.ILinkableLine>();
                        newLinkedLines.Add(newline);
                        pe.RefreshLinkedLines(mi, newLinkedLines);
                    }
                }
            }
        }

        /// <summary>
        /// 如果是鱼骨图节点，取节点相对于鱼头中心构成的平面坐标的相对象限位置。
        /// </summary>
        /// <param name="curCanBeLinkedWidget">根据此参数取鱼头。如果没有鱼头部件，则返回０.</param>
        /// <param name="pe">页面编辑器。</param>
        /// <param name="newCanBeLinkedWidget">新鱼骨节点。</param>
        /// <returns>如果取不到，返回０.</returns>
        private static int GetArea(Widgets.Interfaces.ICanBeLinkedWidget curCanBeLinkedWidget,
            PageEditor pe, Widgets.Interfaces.ICanBeLinkedWidget newCanBeLinkedWidget, ref double preFishLineWidth)
        {
            int newCanLinkedWidgetAtArea = 0;

            List<Widgets.Interfaces.ILinkableLine> linkedLinesOfCurCanLinkedWidget = curCanBeLinkedWidget.GetLinkedLines();
            if (linkedLinesOfCurCanLinkedWidget != null && linkedLinesOfCurCanLinkedWidget.Count == 1)
            {
                PolyLineWidget pl = linkedLinesOfCurCanLinkedWidget[0] as Widgets.PolyLineWidget;
                if (pl != null &&
                        (pl.LineForm == Enums.PolyLineForms.BigFishBone ||
                             pl.LineForm == Enums.PolyLineForms.MediumFishBone)
                    )
                {

                    preFishLineWidth = pl.WidgetLineWidth;

                    if (string.IsNullOrEmpty(pl.StartMasterId) == false)
                    {
                        Widget srcWidget = pe.GetWidget(pl.StartMasterId);
                        if (srcWidget != null)
                        {
                            Rect startRect = srcWidget.OuterRect;
                            Point startCenter = new Point(startRect.X + startRect.Width / 2, startRect.Y + startRect.Height / 2);

                            Rect newRect = newCanBeLinkedWidget.OuterRect;
                            Point newCenter = new Point(newRect.X + newRect.Width / 2, newRect.Y + newRect.Height / 2);

                            if (newCenter.X > startCenter.X)
                            {
                                if (newCenter.Y > startCenter.Y)
                                {
                                    newCanLinkedWidgetAtArea = 4;
                                }
                                else newCanLinkedWidgetAtArea = 1;
                            }
                            else
                            {
                                if (newCenter.Y > startCenter.Y)
                                {
                                    newCanLinkedWidgetAtArea = 3;
                                }
                                else newCanLinkedWidgetAtArea = 2;
                            }
                        }
                    }
                }
            }
            return newCanLinkedWidgetAtArea;
        }

        private static string TryToAddNewPictureBox(PictureBox curPictureBox, double offsetX, double offsetY)
        {
            if (curPictureBox == null) return "　　未传入图片框。";
            if (curPictureBox.MasterEditor == null) return "　　未找到图片所在的页面。";
            if (curPictureBox.MasterEditor.MasterManager == null) return "　　未找到页面管理器。";

            PageEditor pe = curPictureBox.MasterEditor;
            EditorManager manager = curPictureBox.MasterEditor.MasterManager;

            bool addInNewPage = false;
            if (curPictureBox.BottomRight.Y + 46 > pe.EditArea.Bottom)
            {
                int indexOfcurPe = manager.Children.IndexOf(pe);
                if (indexOfcurPe >= (manager.Children.Count - 1))
                {
                    //已是最后一个。
                    Commands.InsertNewPageEditorCommand.Execute();
                    pe = manager.GetMainSelectedPageEditor();
                }
                else
                {
                    pe = manager.Children[indexOfcurPe + 1] as PageEditor;
                }

                if (pe == null) return "　　未找到目标页面。";

                addInNewPage = true;
            }

            ModifingInfo info = new ModifingInfo() { ModifingDescription = "连续添加图片框" };

            manager.GetSelectedPageEditorStatus(info);
            manager.GetSelectedWidgetStatus_Old(info);
            //manager.GetSelectedWidgetStatus_New(info);//要改变选定部件。

            ModifingItem<Action, ModifingInfo> mi = new ModifingItem<Action, ModifingInfo>(info);

            XmlNode widgetSetNode = pe.WidgetSetNode;
            if (widgetSetNode == null) return "　　未找到目标页面Xml数据中的【WidgetSetNode】节点。";

            XmlNode newNode;
            Enums.TitleStyle newTitleLevel;
            if (offsetX < 0)
            {
                if (curPictureBox.TitleLevel > Enums.TitleStyle.MainTitle)
                {
                    newTitleLevel = curPictureBox.TitleLevel - 1;
                }
                else
                {
                    offsetX = 0;//已到最左边。
                    newTitleLevel = curPictureBox.TitleLevel;
                }
            }
            else if (offsetX > 0)
            {
                if (curPictureBox.TitleLevel < Enums.TitleStyle.Normal)
                {
                    newTitleLevel = curPictureBox.TitleLevel + 1;
                }
                else
                {
                    offsetX = 0;//已到最右边。
                    newTitleLevel = curPictureBox.TitleLevel;
                }
            }
            else newTitleLevel = curPictureBox.TitleLevel;

            newNode = widgetSetNode.AppendXmlAsChild(Properties.Resources.PictureBoxXml);
            Widgets.PictureBox pw = new Widgets.PictureBox(pe);
            pw.XmlData = newNode;
            pw.NewID();
            pw.IsImageCollapsed = curPictureBox.IsImageCollapsed;

            if (addInNewPage)
            {
                pw.StartPoint = new Point(curPictureBox.StartPoint.X, pe.EditArea.Top + offsetY);
            }
            else
            {
                pw.StartPoint = new Point(curPictureBox.StartPoint.X, curPictureBox.EndPoint.Y + offsetY);
            }

            if (offsetX < 0)//左缩进减小
            {
                if (curPictureBox.TitleLevel > Enums.TitleStyle.MainTitle)
                {
                    pw.TitleLevel = curPictureBox.TitleLevel - 1;
                }
                else
                {
                    offsetX = 0;//已到最左边。
                    pw.TitleLevel = curPictureBox.TitleLevel;
                }

                if (pw.StartPoint.X + offsetX > 10)
                {
                    pw.StartPoint = new Point(pw.StartPoint.X + offsetX, pw.StartPoint.Y);
                }
            }
            else if (offsetX > 0)
            {
                if (curPictureBox.TitleLevel < Enums.TitleStyle.Normal)
                {
                    pw.TitleLevel = curPictureBox.TitleLevel + 1;
                }
                else
                {
                    offsetX = 0;//已到最右边。
                    pw.TitleLevel = curPictureBox.TitleLevel;
                }

                if (pw.StartPoint.X + offsetX < pe.ActualWidth - 10)
                {
                    pw.StartPoint = new Point(pw.StartPoint.X + offsetX, pw.StartPoint.Y);
                }
            }
            else pw.TitleLevel = curPictureBox.TitleLevel;

            //设置相似属性
            if (curPictureBox.IsWidgetPropertySetted(XmlTags.WidgetOpacityTag)) pw.WidgetOpacity = curPictureBox.WidgetOpacity;
            if (curPictureBox.IsWidgetPropertySetted(XmlTags.IsShadowVisibleTag)) pw.IsShadowVisible = curPictureBox.IsShadowVisible;
            if (curPictureBox.IsWidgetPropertySetted(XmlTags.WidgetLineColorTag)) pw.WidgetLineColor = curPictureBox.WidgetLineColor;
            //if (curPictureBox.IsWidgetPropertySetted(XmlTags.WidgetBackColor)) pw.WidgetBackColor = curPictureBox.WidgetBackColor;
            if (curPictureBox.IsWidgetPropertySetted(XmlTags.WidgetForeColor)) pw.WidgetForeColor = curPictureBox.WidgetForeColor;
            if (curPictureBox.IsWidgetPropertySetted(XmlTags.WidgetLineWidthTag)) pw.WidgetLineWidth = curPictureBox.WidgetLineWidth;

            //Backcolor是特殊的，需要另作处理，因为支持了自定义图像背景
            var srcWidgetBackColorName = BrushManager.GetName(curPictureBox.WidgetBackColor);
            if (string.IsNullOrWhiteSpace(srcWidgetBackColorName) || srcWidgetBackColorName == typeof(ImageBrush).Name)
            {
                if (string.IsNullOrWhiteSpace(curPictureBox.ImageBase64) == false)
                {
                    pw.ImageBase64 = curPictureBox.ImageBase64;
                }
            }
            else
            {
                if (curPictureBox.IsWidgetPropertySetted(XmlTags.WidgetBackColor))
                {
                    pw.WidgetBackColor = curPictureBox.WidgetBackColor;
                }
            }

            Action actInsert = new Action(ActionType.WidgetAdded, pe.Id, pw.Id, null, pw.XmlData.OuterXml);

            pe.AddWidget(pw);

            pw.SelectOnlySelf();
            info.NewMainSelectedWidgetID = pw.Id;

            mi.AddAction(actInsert);

            #region 添加相似关系线
            if (addInNewPage == false)
            {
                AddSimilarLinkedLine(curPictureBox, pe, pw, mi);
            }
            #endregion

            manager.RegisterModifingItem(mi);
            manager.RefreshAutoNumberStrings();

            return string.Empty;
        }

        private static string TryToAddNewEllipse(EllipseWidget curEllipse, double offsetX, double offsetY)
        {
            if (curEllipse == null) return "　　未传入圆形部件。";
            if (curEllipse.MasterEditor == null) return "　　未找到圆形部件所在的页面。";
            if (curEllipse.MasterEditor.MasterManager == null) return "　　未找到页面管理器。";

            PageEditor pe = curEllipse.MasterEditor;
            EditorManager manager = curEllipse.MasterEditor.MasterManager;

            bool addInNewPage = false;
            if (curEllipse.BottomRight.Y + 46 > pe.EditArea.Bottom)
            {
                int indexOfcurPe = manager.Children.IndexOf(pe);
                if (indexOfcurPe >= (manager.Children.Count - 1))
                {
                    //已是最后一个。
                    Commands.InsertNewPageEditorCommand.Execute();
                    pe = manager.GetMainSelectedPageEditor();
                }
                else
                {
                    pe = manager.Children[indexOfcurPe + 1] as PageEditor;
                }

                if (pe == null) return "　　未找到目标页面。";

                addInNewPage = true;
            }

            ModifingInfo info = new ModifingInfo() { ModifingDescription = "连续添加圆形" };

            manager.GetSelectedPageEditorStatus(info);
            manager.GetSelectedWidgetStatus_Old(info);
            //manager.GetSelectedWidgetStatus_New(info);//要改变选定部件。

            ModifingItem<Action, ModifingInfo> mi = new ModifingItem<Action, ModifingInfo>(info);

            XmlNode widgetSetNode = pe.WidgetSetNode;
            if (widgetSetNode == null) return "　　未找到目标页面Xml数据中的【WidgetSetNode】节点。";

            XmlNode newNode;
            Enums.TitleStyle newTitleLevel;
            if (offsetX < 0)
            {
                if (curEllipse.TitleLevel > Enums.TitleStyle.MainTitle)
                {
                    newTitleLevel = curEllipse.TitleLevel - 1;
                }
                else
                {
                    offsetX = 0;//已到最左边。
                    newTitleLevel = curEllipse.TitleLevel;
                }
            }
            else if (offsetX > 0)
            {
                if (curEllipse.TitleLevel < Enums.TitleStyle.Normal)
                {
                    newTitleLevel = curEllipse.TitleLevel + 1;
                }
                else
                {
                    offsetX = 0;//已到最右边。
                    newTitleLevel = curEllipse.TitleLevel;
                }
            }
            else newTitleLevel = curEllipse.TitleLevel;

            newNode = widgetSetNode.AppendXmlAsChild(Properties.Resources.EllipseXml);
            Widgets.EllipseWidget ew = new EllipseWidget(pe);
            ew.XmlData = newNode;
            ew.NewID();
            ew.TitleLevel = newTitleLevel;

            if (addInNewPage)
            {
                ew.StartPoint = new Point(curEllipse.StartPoint.X, pe.EditArea.Top + offsetY);
                ew.EndPoint = new Point(curEllipse.EndPoint.X,
                    ew.StartPoint.Y + (curEllipse.EndPoint.Y - curEllipse.StartPoint.Y));
            }
            else
            {
                ew.StartPoint = new Point(curEllipse.StartPoint.X, curEllipse.EndPoint.Y + offsetY);
                ew.EndPoint = new Point(curEllipse.EndPoint.X,
                    ew.StartPoint.Y + (curEllipse.EndPoint.Y - curEllipse.StartPoint.Y));
            }

            if (offsetX < 0)//左缩进减小
            {
                if (ew.StartPoint.X + offsetX > 10)
                {
                    ew.StartPoint = new Point(ew.StartPoint.X + offsetX, ew.StartPoint.Y);
                    //rw.EndPoint不改，保持与当前矩形一致。
                }
            }
            else if (offsetX > 0)
            {
                if (ew.StartPoint.X + offsetX < pe.ActualWidth - 10)
                {
                    ew.StartPoint = new Point(ew.StartPoint.X + offsetX, ew.StartPoint.Y);
                    if (ew.StartPoint.X > ew.EndPoint.X - 10)//通常，新矩形右边保持与当前矩形一致。
                    {
                        ew.EndPoint = new Point(ew.EndPoint.X + offsetX, ew.EndPoint.Y);
                        //如果增加缩进导致新矩形宽度过小，则新矩形右边也缩进。
                    }
                }
            }

            //设置相似属性。
            if (curEllipse.IsWidgetPropertySetted(XmlTags.WidgetOpacityTag)) ew.WidgetOpacity = curEllipse.WidgetOpacity;
            if (curEllipse.IsWidgetPropertySetted(XmlTags.IsShadowVisibleTag)) ew.IsShadowVisible = curEllipse.IsShadowVisible;
            if (curEllipse.IsWidgetPropertySetted(XmlTags.WidgetLineColorTag)) ew.WidgetLineColor = curEllipse.WidgetLineColor;
            //if (curEllipse.IsWidgetPropertySetted(XmlTags.WidgetBackColor)) ew.WidgetBackColor = curEllipse.WidgetBackColor;
            if (curEllipse.IsWidgetPropertySetted(XmlTags.WidgetForeColor)) ew.WidgetForeColor = curEllipse.WidgetForeColor;
            if (curEllipse.IsWidgetPropertySetted(XmlTags.LineDashTag)) ew.LineDash = curEllipse.LineDash;
            if (curEllipse.IsWidgetPropertySetted(XmlTags.WidgetLineWidthTag)) ew.WidgetLineWidth = curEllipse.WidgetLineWidth;

            //Backcolor是特殊的，需要另作处理，因为支持了自定义图像背景
            var srcWidgetBackColorName = BrushManager.GetName(curEllipse.WidgetBackColor);
            if (string.IsNullOrWhiteSpace(srcWidgetBackColorName) || srcWidgetBackColorName == typeof(ImageBrush).Name)
            {
                if (string.IsNullOrWhiteSpace(curEllipse.ImageBase64) == false)
                {
                    ew.ImageBase64 = curEllipse.ImageBase64;
                }
            }
            else
            {
                if (curEllipse.IsWidgetPropertySetted(XmlTags.WidgetBackColor))
                {
                    ew.WidgetBackColor = curEllipse.WidgetBackColor;
                }
            }

            Action actInsert = new Action(ActionType.WidgetAdded, pe.Id, ew.Id, null, ew.XmlData.OuterXml);

            pe.AddWidget(ew);

            ew.SelectOnlySelf();
            info.NewMainSelectedWidgetID = ew.Id;

            mi.AddAction(actInsert);

            #region 添加相似关系线
            if (addInNewPage == false)
            {
                AddSimilarLinkedLine(curEllipse, pe, ew, mi);
            }
            #endregion

            manager.RegisterModifingItem(mi);
            manager.RefreshAutoNumberStrings();

            return string.Empty;
        }

        private static string TryToAddNewRectangle(RectangleWidget curRectangle, double offsetX, double offsetY)
        {
            if (curRectangle == null) return "　　未传入矩形部件。";
            if (curRectangle.MasterEditor == null) return "　　未找到传入的矩形部件所在的页面。";
            if (curRectangle.MasterEditor.MasterManager == null) return "　　未找到页面管理器。";

            PageEditor pe = curRectangle.MasterEditor;
            EditorManager manager = curRectangle.MasterEditor.MasterManager;

            bool addInNewPage = false;
            if (curRectangle.BottomRight.Y + 46 > pe.EditArea.Bottom)
            {
                int indexOfcurPe = manager.Children.IndexOf(pe);
                if (indexOfcurPe >= (manager.Children.Count - 1))
                {
                    //已是最后一个。
                    Commands.InsertNewPageEditorCommand.Execute();
                    pe = manager.GetMainSelectedPageEditor();
                }
                else
                {
                    pe = manager.Children[indexOfcurPe + 1] as PageEditor;
                }

                if (pe == null) return "　　未找到目标页面。";

                addInNewPage = true;
            }

            ModifingInfo info = new ModifingInfo() { ModifingDescription = "连续添加矩形" };

            manager.GetSelectedPageEditorStatus(info);
            manager.GetSelectedWidgetStatus_Old(info);
            //manager.GetSelectedWidgetStatus_New(info);//要改变选定部件。

            ModifingItem<Action, ModifingInfo> mi = new ModifingItem<Action, ModifingInfo>(info);

            XmlNode widgetSetNode = pe.WidgetSetNode;
            if (widgetSetNode == null) return "　　未找到目标页面Xml数据中的【WidgetSetNode】节点。";

            XmlNode newNode;
            Enums.TitleStyle newTitleLevel;
            if (offsetX < 0)
            {
                if (curRectangle.TitleLevel > Enums.TitleStyle.MainTitle)
                {
                    newTitleLevel = curRectangle.TitleLevel - 1;
                }
                else
                {
                    offsetX = 0;//已到最左边。
                    newTitleLevel = curRectangle.TitleLevel;
                }
            }
            else if (offsetX > 0)
            {
                if (curRectangle.TitleLevel < Enums.TitleStyle.Normal)
                {
                    newTitleLevel = curRectangle.TitleLevel + 1;
                }
                else
                {
                    offsetX = 0;//已到最右边。
                    newTitleLevel = curRectangle.TitleLevel;
                }
            }
            else newTitleLevel = curRectangle.TitleLevel;

            newNode = widgetSetNode.AppendXmlAsChild(Properties.Resources.RectangleXml);
            Widgets.RectangleWidget rw = new RectangleWidget(pe);
            rw.XmlData = newNode;
            rw.NewID();
            rw.TitleLevel = newTitleLevel;

            if (addInNewPage)
            {
                rw.StartPoint = new Point(curRectangle.StartPoint.X, pe.EditArea.Top + offsetY);
                if (curRectangle.FixTextWidth)
                {
                    rw.EndPoint = new Point(curRectangle.EndPoint.X, rw.StartPoint.Y + manager.DefaultFontSize + 10);
                }
                else
                {
                    //对于文本非自动折行的矩形框，只要简单地保持一样的尺寸即可。
                    rw.EndPoint = new Point(curRectangle.EndPoint.X,
                        rw.StartPoint.Y + (curRectangle.EndPoint.Y - curRectangle.StartPoint.Y));
                }
            }
            else
            {
                rw.StartPoint = new Point(curRectangle.StartPoint.X, curRectangle.EndPoint.Y + offsetY);
                if (curRectangle.FixTextWidth)
                {
                    rw.EndPoint = new Point(curRectangle.EndPoint.X, rw.StartPoint.Y + manager.DefaultFontSize + 10);
                }
                else
                {
                    //对于文本非自动折行的矩形框，只要简单地保持一样的尺寸即可。
                    rw.EndPoint = new Point(curRectangle.EndPoint.X,
                        rw.StartPoint.Y + (curRectangle.EndPoint.Y - curRectangle.StartPoint.Y));
                }
            }

            if (offsetX < 0)//左缩进减小
            {
                if (rw.StartPoint.X + offsetX > 10)
                {
                    rw.StartPoint = new Point(rw.StartPoint.X + offsetX, rw.StartPoint.Y);
                    //rw.EndPoint不改，保持与当前矩形一致。
                }
            }
            else if (offsetX > 0)
            {
                if (rw.StartPoint.X + offsetX < pe.ActualWidth - 10)
                {
                    rw.StartPoint = new Point(rw.StartPoint.X + offsetX, rw.StartPoint.Y);
                    if (rw.StartPoint.X > rw.EndPoint.X - 10)//通常，新矩形右边保持与当前矩形一致。
                    {
                        rw.EndPoint = new Point(rw.EndPoint.X + offsetX, rw.EndPoint.Y);
                        //如果增加缩进导致新矩形宽度过小，则新矩形右边也缩进。
                    }
                }
            }

            //设置相似属性。
            if (curRectangle.IsWidgetPropertySetted(XmlTags.WidgetOpacityTag)) rw.WidgetOpacity = curRectangle.WidgetOpacity;
            if (curRectangle.IsWidgetPropertySetted(XmlTags.IsShadowVisibleTag)) rw.IsShadowVisible = curRectangle.IsShadowVisible;
            if (curRectangle.IsWidgetPropertySetted(XmlTags.WidgetLineColorTag)) rw.WidgetLineColor = curRectangle.WidgetLineColor;
            //if (curRectangle.IsWidgetPropertySetted(XmlTags.WidgetBackColor)) rw.WidgetBackColor = curRectangle.WidgetBackColor;
            if (curRectangle.IsWidgetPropertySetted(XmlTags.WidgetForeColor)) rw.WidgetForeColor = curRectangle.WidgetForeColor;
            if (curRectangle.IsWidgetPropertySetted(XmlTags.LineDashTag)) rw.LineDash = curRectangle.LineDash;
            if (curRectangle.IsWidgetPropertySetted(XmlTags.WidgetLineWidthTag)) rw.WidgetLineWidth = curRectangle.WidgetLineWidth;
            if (curRectangle.IsWidgetPropertySetted(XmlTags.FixTextWidthTag)) rw.FixTextWidth = curRectangle.FixTextWidth;
            if (curRectangle.IsWidgetPropertySetted(XmlTags.RadiusTag)) rw.Radius = curRectangle.Radius;

            //Backcolor是特殊的，需要另作处理，因为支持了自定义图像背景
            var srcWidgetBackColorName = BrushManager.GetName(curRectangle.WidgetBackColor);
            if (string.IsNullOrWhiteSpace(srcWidgetBackColorName) || srcWidgetBackColorName == typeof(ImageBrush).Name)
            {
                if (string.IsNullOrWhiteSpace(curRectangle.ImageBase64) == false)
                {
                    rw.ImageBase64 = curRectangle.ImageBase64;
                }
            }
            else
            {
                if (curRectangle.IsWidgetPropertySetted(XmlTags.WidgetBackColor))
                {
                    rw.WidgetBackColor = curRectangle.WidgetBackColor;
                }
            }

            Action actInsert = new Action(ActionType.WidgetAdded, pe.Id, rw.Id, null, rw.XmlData.OuterXml);

            pe.AddWidget(rw);

            rw.SelectOnlySelf();
            info.NewMainSelectedWidgetID = rw.Id;

            mi.AddAction(actInsert);

            //RectangleWidget.ResetRectangleWidgetHeight(mi, rw);//重设高度。会导致不必要地将新添加的矩形变矮。

            #region 添加相似关系线
            if (addInNewPage == false)
            {
                AddSimilarLinkedLine(curRectangle, pe, rw, mi);
            }
            #endregion

            manager.RegisterModifingItem(mi);
            manager.RefreshAutoNumberStrings();

            return string.Empty;
        }

        private static string TryToAddNewRhomb(RhombWidget curRhomb, double offsetX, double offsetY)
        {
            if (curRhomb == null) return "　　未传入菱形部件。";
            if (curRhomb.MasterEditor == null) return "未找到传入的菱形部件所在的页面。";
            if (curRhomb.MasterEditor.MasterManager == null) return "　　未找到页面管理器。";

            PageEditor pe = curRhomb.MasterEditor;
            EditorManager manager = curRhomb.MasterEditor.MasterManager;

            bool addInNewPage = false;
            if (curRhomb.BottomRight.Y + 46 > pe.EditArea.Bottom)
            {
                int indexOfcurPe = manager.Children.IndexOf(pe);
                if (indexOfcurPe >= (manager.Children.Count - 1))
                {
                    //已是最后一个。
                    Commands.InsertNewPageEditorCommand.Execute();
                    pe = manager.GetMainSelectedPageEditor();
                }
                else
                {
                    pe = manager.Children[indexOfcurPe + 1] as PageEditor;
                }

                if (pe == null) return "　　未找到目标页面。";

                addInNewPage = true;
            }

            ModifingInfo info = new ModifingInfo() { ModifingDescription = "连续添加菱形" };

            manager.GetSelectedPageEditorStatus(info);
            manager.GetSelectedWidgetStatus_Old(info);
            //manager.GetSelectedWidgetStatus_New(info);//要改变选定部件。

            ModifingItem<Action, ModifingInfo> mi = new ModifingItem<Action, ModifingInfo>(info);

            XmlNode widgetSetNode = pe.WidgetSetNode;
            if (widgetSetNode == null) return "　　未找到目标页面Xml数据中的【WidgetSetNode】节点。";

            XmlNode newNode;
            Enums.TitleStyle newTitleLevel;
            if (offsetX < 0)
            {
                if (curRhomb.TitleLevel > Enums.TitleStyle.MainTitle)
                {
                    newTitleLevel = curRhomb.TitleLevel - 1;
                }
                else
                {
                    offsetX = 0;//已到最左边。
                    newTitleLevel = curRhomb.TitleLevel;
                }
            }
            else if (offsetX > 0)
            {
                if (curRhomb.TitleLevel < Enums.TitleStyle.Normal)
                {
                    newTitleLevel = curRhomb.TitleLevel + 1;
                }
                else
                {
                    offsetX = 0;//已到最右边。
                    newTitleLevel = curRhomb.TitleLevel;
                }
            }
            else newTitleLevel = curRhomb.TitleLevel;

            newNode = widgetSetNode.AppendXmlAsChild(Properties.Resources.RhombXml);
            Widgets.RhombWidget rw = new RhombWidget(pe);
            rw.XmlData = newNode;
            rw.NewID();
            rw.TitleLevel = newTitleLevel;

            if (addInNewPage)
            {
                rw.StartPoint = new Point(curRhomb.StartPoint.X, pe.EditArea.Top + offsetY);
                rw.EndPoint = new Point(curRhomb.EndPoint.X,
                    rw.StartPoint.Y + (curRhomb.EndPoint.Y - curRhomb.StartPoint.Y));
            }
            else
            {
                rw.StartPoint = new Point(curRhomb.StartPoint.X, curRhomb.EndPoint.Y + offsetY);
                rw.EndPoint = new Point(curRhomb.EndPoint.X,
                    rw.StartPoint.Y + (curRhomb.EndPoint.Y - curRhomb.StartPoint.Y));
            }

            if (offsetX < 0)//左缩进减小
            {
                if (rw.StartPoint.X + offsetX > 10)
                {
                    rw.StartPoint = new Point(rw.StartPoint.X + offsetX, rw.StartPoint.Y);
                    //rw.EndPoint不改，保持与当前矩形一致。
                }
            }
            else if (offsetX > 0)
            {
                if (rw.StartPoint.X + offsetX < pe.ActualWidth - 10)
                {
                    rw.StartPoint = new Point(rw.StartPoint.X + offsetX, rw.StartPoint.Y);
                    if (rw.StartPoint.X > rw.EndPoint.X - 10)//通常，新矩形右边保持与当前矩形一致。
                    {
                        rw.EndPoint = new Point(rw.EndPoint.X + offsetX, rw.EndPoint.Y);
                        //如果增加缩进导致新矩形宽度过小，则新矩形右边也缩进。
                    }
                }
            }

            //设置相似属性。
            if (curRhomb.IsWidgetPropertySetted(XmlTags.WidgetOpacityTag)) rw.WidgetOpacity = curRhomb.WidgetOpacity;
            if (curRhomb.IsWidgetPropertySetted(XmlTags.IsShadowVisibleTag)) rw.IsShadowVisible = curRhomb.IsShadowVisible;
            if (curRhomb.IsWidgetPropertySetted(XmlTags.WidgetLineColorTag)) rw.WidgetLineColor = curRhomb.WidgetLineColor;
            //if (curRhomb.IsWidgetPropertySetted(XmlTags.WidgetBackColor)) rw.WidgetBackColor = curRhomb.WidgetBackColor;
            if (curRhomb.IsWidgetPropertySetted(XmlTags.WidgetForeColor)) rw.WidgetForeColor = curRhomb.WidgetForeColor;
            if (curRhomb.IsWidgetPropertySetted(XmlTags.LineDashTag)) rw.LineDash = curRhomb.LineDash;
            if (curRhomb.IsWidgetPropertySetted(XmlTags.WidgetLineWidthTag)) rw.WidgetLineWidth = curRhomb.WidgetLineWidth;
            if (curRhomb.IsWidgetPropertySetted(XmlTags.WidgetFormTag)) rw.WidgetForm = curRhomb.WidgetForm;

            //Backcolor是特殊的，需要另作处理，因为支持了自定义图像背景
            var srcWidgetBackColorName = BrushManager.GetName(curRhomb.WidgetBackColor);
            if (string.IsNullOrWhiteSpace(srcWidgetBackColorName) || srcWidgetBackColorName == typeof(ImageBrush).Name)
            {
                if (string.IsNullOrWhiteSpace(curRhomb.ImageBase64) == false)
                {
                    rw.ImageBase64 = curRhomb.ImageBase64;
                }
            }
            else
            {
                if (curRhomb.IsWidgetPropertySetted(XmlTags.WidgetBackColor))
                {
                    rw.WidgetBackColor = curRhomb.WidgetBackColor;
                }
            }

            Action actInsert = new Action(ActionType.WidgetAdded, pe.Id, rw.Id, null, rw.XmlData.OuterXml);

            pe.AddWidget(rw);

            rw.SelectOnlySelf();
            info.NewMainSelectedWidgetID = rw.Id;

            mi.AddAction(actInsert);

            #region 添加相似关系线
            if (addInNewPage == false)
            {
                AddSimilarLinkedLine(curRhomb, pe, rw, mi);
            }
            #endregion

            manager.RegisterModifingItem(mi);
            manager.RefreshAutoNumberStrings();

            return string.Empty;
        }

        private static string TryToAddTriangle(TriangleWidget curTriangle, double offsetX, double offsetY)
        {
            if (curTriangle == null) return "　　未传入三角形部件。";
            if (curTriangle.MasterEditor == null) return "　　未找到传入的三角形部件所在的页面。";
            if (curTriangle.MasterEditor.MasterManager == null) return "　　未找到页面管理器。";

            PageEditor pe = curTriangle.MasterEditor;
            EditorManager manager = curTriangle.MasterEditor.MasterManager;

            bool addInNewPage = false;
            if (curTriangle.BottomRight.Y + 46 > pe.EditArea.Bottom)
            {
                int indexOfcurPe = manager.Children.IndexOf(pe);
                if (indexOfcurPe >= (manager.Children.Count - 1))
                {
                    //已是最后一个。
                    Commands.InsertNewPageEditorCommand.Execute();
                    pe = manager.GetMainSelectedPageEditor();
                }
                else
                {
                    pe = manager.Children[indexOfcurPe + 1] as PageEditor;
                }

                if (pe == null) return "　　未找到目标页面。";

                addInNewPage = true;
            }

            ModifingInfo info = new ModifingInfo() { ModifingDescription = "连续添加三角形" };

            manager.GetSelectedPageEditorStatus(info);
            manager.GetSelectedWidgetStatus_Old(info);
            //manager.GetSelectedWidgetStatus_New(info);//要改变选定部件。

            ModifingItem<Action, ModifingInfo> mi = new ModifingItem<Action, ModifingInfo>(info);

            XmlNode widgetSetNode = pe.WidgetSetNode;
            if (widgetSetNode == null) return "　　未找到目标页面Xml数据中的【WidgetSetNode】节点。";

            XmlNode newNode;
            Enums.TitleStyle newTitleLevel;
            if (offsetX < 0)
            {
                if (curTriangle.TitleLevel > Enums.TitleStyle.MainTitle)
                {
                    newTitleLevel = curTriangle.TitleLevel - 1;
                }
                else
                {
                    offsetX = 0;//已到最左边。
                    newTitleLevel = curTriangle.TitleLevel;
                }
            }
            else if (offsetX > 0)
            {
                if (curTriangle.TitleLevel < Enums.TitleStyle.Normal)
                {
                    newTitleLevel = curTriangle.TitleLevel + 1;
                }
                else
                {
                    offsetX = 0;//已到最右边。
                    newTitleLevel = curTriangle.TitleLevel;
                }
            }
            else newTitleLevel = curTriangle.TitleLevel;

            newNode = widgetSetNode.AppendXmlAsChild(Properties.Resources.TriangleXml);
            Widgets.TriangleWidget tw = new TriangleWidget(pe);
            tw.XmlData = newNode;
            tw.NewID();
            tw.TitleLevel = newTitleLevel;

            if (addInNewPage)
            {
                tw.StartPoint = new Point(curTriangle.StartPoint.X, pe.EditArea.Top + offsetY);
                tw.EndPoint = new Point(curTriangle.EndPoint.X,
                    tw.StartPoint.Y + (curTriangle.EndPoint.Y - curTriangle.StartPoint.Y));

                tw.CenterCPPoint = new Point(curTriangle.CenterCPPoint.X,
                    tw.StartPoint.Y + (curTriangle.CenterCPPoint.Y - curTriangle.StartPoint.Y));
            }
            else
            {
                tw.StartPoint = new Point(curTriangle.StartPoint.X, curTriangle.EndPoint.Y + offsetY);
                tw.EndPoint = new Point(curTriangle.EndPoint.X,
                    tw.StartPoint.Y + (curTriangle.EndPoint.Y - curTriangle.StartPoint.Y));

                tw.CenterCPPoint = new Point(curTriangle.CenterCPPoint.X,
                    tw.StartPoint.Y + (curTriangle.CenterCPPoint.Y - curTriangle.StartPoint.Y));
            }

            if (offsetX < 0)//左缩进减小
            {
                if (tw.StartPoint.X + offsetX > 10)
                {
                    tw.StartPoint = new Point(tw.StartPoint.X + offsetX, tw.StartPoint.Y);
                    //rw.EndPoint不改，保持与当前矩形一致。
                }
            }
            else if (offsetX > 0)
            {
                if (tw.StartPoint.X + offsetX < pe.ActualWidth - 10)
                {
                    tw.StartPoint = new Point(tw.StartPoint.X + offsetX, tw.StartPoint.Y);
                    if (tw.StartPoint.X > tw.EndPoint.X - 10)//通常，新矩形右边保持与当前矩形一致。
                    {
                        tw.EndPoint = new Point(tw.EndPoint.X + offsetX, tw.EndPoint.Y);
                        //如果增加缩进导致新矩形宽度过小，则新矩形右边也缩进。
                    }
                }
            }

            //设置相似属性。
            if (curTriangle.IsWidgetPropertySetted(XmlTags.WidgetOpacityTag)) tw.WidgetOpacity = curTriangle.WidgetOpacity;
            if (curTriangle.IsWidgetPropertySetted(XmlTags.IsShadowVisibleTag)) tw.IsShadowVisible = curTriangle.IsShadowVisible;
            if (curTriangle.IsWidgetPropertySetted(XmlTags.WidgetLineColorTag)) tw.WidgetLineColor = curTriangle.WidgetLineColor;
            //if (curTriangle.IsWidgetPropertySetted(XmlTags.WidgetBackColor)) tw.WidgetBackColor = curTriangle.WidgetBackColor;
            if (curTriangle.IsWidgetPropertySetted(XmlTags.WidgetForeColor)) tw.WidgetForeColor = curTriangle.WidgetForeColor;
            if (curTriangle.IsWidgetPropertySetted(XmlTags.LineDashTag)) tw.LineDash = curTriangle.LineDash;
            if (curTriangle.IsWidgetPropertySetted(XmlTags.WidgetLineWidthTag)) tw.WidgetLineWidth = curTriangle.WidgetLineWidth;

            //Backcolor是特殊的，需要另作处理，因为支持了自定义图像背景
            var srcWidgetBackColorName = BrushManager.GetName(curTriangle.WidgetBackColor);
            if (string.IsNullOrWhiteSpace(srcWidgetBackColorName) || srcWidgetBackColorName == typeof(ImageBrush).Name)
            {
                if (string.IsNullOrWhiteSpace(curTriangle.ImageBase64) == false)
                {
                    tw.ImageBase64 = curTriangle.ImageBase64;
                }
            }
            else
            {
                if (curTriangle.IsWidgetPropertySetted(XmlTags.WidgetBackColor))
                {
                    tw.WidgetBackColor = curTriangle.WidgetBackColor;
                }
            }

            Action actInsert = new Action(ActionType.WidgetAdded, pe.Id, tw.Id, null, tw.XmlData.OuterXml);

            pe.AddWidget(tw);

            tw.SelectOnlySelf();
            info.NewMainSelectedWidgetID = tw.Id;

            mi.AddAction(actInsert);

            #region 添加相似关系线
            if (addInNewPage == false)
            {
                AddSimilarLinkedLine(curTriangle, pe, tw, mi);
            }
            #endregion

            manager.RegisterModifingItem(mi);
            manager.RefreshAutoNumberStrings();

            return string.Empty;
        }

        #endregion
    }
}
